package variabilitysmelldetection.plugin.preferences;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;

import variabilitysmelldetection.measurement.Measurement;
import variabilitysmelldetection.measurement.measures.Measure;
import variabilitysmelldetection.plugin.Activator;
import variabilitysmelldetection.plugin.preferences.fields.DoubleFieldEditor;
import variabilitysmelldetection.plugin.preferences.fields.LabelFieldEditor;

/**
 * This class represents a preference page that
 * is contributed to the Preferences dialog. By 
 * subclassing <samp>FieldEditorPreferencePage</samp>, we
 * can use the field support built into JFace that allows
 * us to create a page that is small and knows how to 
 * save, restore and apply itself.
 * <p>
 * This page is used to modify preferences only. They
 * are stored in the preference store that belongs to
 * the main plug-in class. That way, preferences can
 * be accessed directly via the preference store.
 */

public class VSDPreferences extends FieldEditorPreferencePage
implements IWorkbenchPreferencePage {

	private TableViewer viewer;

	public VSDPreferences() {
		super(GRID);
		setPreferenceStore(Activator.getDefault().getPreferenceStore());
		setDescription("Define the values that will be used as thresholds in code smells detection strategies.");
	}

	/**
	 * Creates the field editors. Field editors are abstractions of
	 * the common GUI blocks needed to manipulate various types
	 * of preferences. Each field editor knows how to save and
	 * restore itself.
	 */
	public void createFieldEditors() {

		GridLayoutFactory.swtDefaults().numColumns(2).applyTo(getFieldEditorParent());

		Label separator = new Label(getFieldEditorParent(), SWT.SEPARATOR | SWT.HORIZONTAL);
		GridDataFactory.fillDefaults().span(3, 1).grab(true, false).applyTo(separator);

		Group groupGodMethod = new Group(getFieldEditorParent(), SWT.SHADOW_OUT);
		groupGodMethod.setText("God Method thresholds");
		GridDataFactory.defaultsFor(groupGodMethod).grab(true, false).span(2, 1).applyTo(groupGodMethod);
				
		addField(new LabelFieldEditor("Strategy: ((NOOr+NMR) > HIGH) OR ((MLoC > AVG) AND ((Cyclo/MLoC) > HIGH))", groupGodMethod));
		addField(new DoubleFieldEditor(PreferenceConstants.GODMETHOD_NOOR_NMR_THRESHOLD, "NOOR+NMR:", groupGodMethod));
		addField(new DoubleFieldEditor(PreferenceConstants.GODMETHOD_MLOC_THRESHOLD, "MLoC:", groupGodMethod));
		addField(new DoubleFieldEditor(PreferenceConstants.GODMETHOD_CYCLO_THRESHOLD, "Cyclo/MLoC:", groupGodMethod));

		Group groupGodClass = new Group(getFieldEditorParent(), SWT.SHADOW_OUT);
		groupGodClass.setText("God Class thresholds");
		GridDataFactory.defaultsFor(groupGodClass).grab(true, false).span(2, 1).applyTo(groupGodClass);

		addField(new LabelFieldEditor("Strategy: (NCR > HIGH) OR ((LoC > HIGH) AND (CBO > LOW) AND ((WMC/LoC) > HIGH))", groupGodClass));
		addField(new DoubleFieldEditor(PreferenceConstants.GODCLASS_LOC_THRESHOLD, "LoC:", groupGodClass));
		addField(new DoubleFieldEditor(PreferenceConstants.GODCLASS_CBO_THRESHOLD, "CBO:", groupGodClass));
		addField(new DoubleFieldEditor(PreferenceConstants.GODCLASS_CYCLO_THRESHOLD, "WMC/LoC:", groupGodClass));
		addField(new DoubleFieldEditor(PreferenceConstants.GODCLASS_NCR_THRESHOLD, "NCR:", groupGodClass));

		Group groupShotgunSurgery = new Group(getFieldEditorParent(), SWT.SHADOW_OUT);
		groupShotgunSurgery.setText("Shotgun Surgery thresholds");
		GridDataFactory.defaultsFor(groupShotgunSurgery).grab(true, false).span(2, 1).applyTo(groupShotgunSurgery);

		addField(new LabelFieldEditor("Strategy: (NCR > HIGH) AND (NOA > HIGH) AND (CBO > LOW) AND (NOO > HIGH)", groupShotgunSurgery));
		addField(new DoubleFieldEditor(PreferenceConstants.SHOTGUNSURGERY_NOA_THRESHOLD, "NOA:", groupShotgunSurgery));
		addField(new DoubleFieldEditor(PreferenceConstants.SHOTGUNSURGERY_NCR_THRESHOLD, "NCR:", groupShotgunSurgery));
		addField(new DoubleFieldEditor(PreferenceConstants.SHOTGUNSURGERY_NOO_THRESHOLD, "NOO:", groupShotgunSurgery));
		addField(new DoubleFieldEditor(PreferenceConstants.SHOTGUNSURGERY_CBO_THRESHOLD, "CBO:", groupShotgunSurgery));

		createMeasuresTable();

	}

	private TableViewer createMeasuresTable() {

		viewer = new TableViewer(getFieldEditorParent(), SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);

		createColumns(getFieldEditorParent(), viewer);

		final Table table = viewer.getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		viewer.setContentProvider(new ArrayContentProvider());
		List<Measure> measures = new ArrayList<Measure>();
		measures.addAll(Arrays.asList(Measurement.getMethodMeasures()));
		measures.addAll(Arrays.asList(Measurement.getComponentMeasures()));
		viewer.setInput(measures);

		// define layout for the viewer
		GridData gridData = new GridData();
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalSpan = 2;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		viewer.getControl().setLayoutData(gridData);
		return viewer;
	}

	// create the columns for the table
	private void createColumns(final Composite parent, final TableViewer viewer) {

		TableViewerColumn col = createTableViewerColumn("Acronym", 100);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Measure m = (Measure) element;
				return m.getAcronym();
			}
		});

		col = createTableViewerColumn("Name", 180);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Measure m = (Measure) element;
				return m.getName();
			}
		});
	}

	private TableViewerColumn createTableViewerColumn(String title, int bound) {
		final TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
		final TableColumn column = viewerColumn.getColumn();
		column.setText(title);
		column.setWidth(bound);
		column.setResizable(true);
		column.setMoveable(true);
		return viewerColumn;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
	 */
	public void init(IWorkbench workbench) {
	}

}